<script lang="ts">
export default {
  name: "sql"
};
</script>

<script setup lang="ts">
import dayjs from "dayjs";
import { getList, remove, get, add, update } from "/@/api/system/dynamicSql";
import { FormInstance } from "element-plus";
import { reactive, ref, onMounted, toRaw, computed } from "vue";
import { EpTableProBar } from "/@/components/ReTable";
import { message } from "@pureadmin/components";
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
import { getAllList } from "/@/api/system/datasource";
import { FormRules } from "element-plus/es";
import { ResponseType } from "/@/utils/http";
import { ReTextHighlight } from "/@/components/ReTextHighlight";
import { Delete, Plus } from "@element-plus/icons-vue";
import { getAllList as getCommonValidatorAllList } from "/@/api/system/commonValidator";

const form = reactive({
  sqlTag: "",
  dataSourceName: ""
});
const editForm = ref({
  id: null,
  sqlTag: "",
  sqlResultKey: "",
  sqlContent: "",
  sqlType: "",
  dataSourceName: "",
  parameterValidationList: []
});

const editRules = reactive<FormRules>({
  sqlTag: [{ required: true, message: "sql标签不能为空" }],
  sqlResultKey: [{ required: true, message: "结果key不能为空" }],
  sqlContent: [{ required: true, message: "sql内容不能为空" }],
  sqlType: [{ required: true, message: "结果类型不能为空" }]
});

let dataList = ref([]);
let pageSize = ref(10);
let pageNum = ref(1);
let totalPage = ref(0);
let loading = ref(true);
let editLoading = ref(false);
let editId = ref(null);
let editShow = ref(false);
const sourceList = ref([]);
const regexTypeList = ref([]);

const formRef = ref<FormInstance>();
const editFormRef = ref<FormInstance>();

let isUpdate = computed(() => editId.value != null);

const onSubmit = async () => {
  await editFormRef.value.validate((valid, fields) => {
    if (valid) {
      const data: any = toRaw(editForm.value);
      editLoading.value = true;
      let resp: ResponseType;
      if (isUpdate.value) {
        resp = update(data);
      } else {
        resp = add(data);
      }
      resp
        .then(resp => {
          if (resp.code === 200) {
            message.success(resp.msg);
            editShow.value = false;
            onSearch();
          } else {
            message.error(resp.msg);
          }
        })
        .finally(() => (editLoading.value = false));
    }
  });
};

function handleUpdate(row) {
  editFormRef.value?.resetFields();
  editId.value = row.id;
  editLoading.value = true;
  get(row.id)
    .then(res => {
      const {
        id,
        sqlTag,
        sqlResultKey,
        sqlContent,
        sqlType,
        dataSourceName,
        parameterValidationList
      } = res.data;
      editForm.value = {
        id,
        sqlTag,
        sqlResultKey,
        sqlContent,
        sqlType,
        dataSourceName,
        parameterValidationList
      };
    })
    .finally(() => (editLoading.value = false));
  editShow.value = true;
}

function handleDelete(row) {
  loading.value = true;
  remove(row.id).then(resp => {
    if (resp.code === 200) {
      message.success(resp.msg);
      onSearch();
    } else {
      message.error(resp.msg);
    }
  });
}

function handleCurrentChange(val: number) {
  pageNum.value = val;
  onSearch();
}

function handleSizeChange(val: number) {
  pageSize.value = val;
  onSearch();
}

function handleSelectionChange(val) {
  console.log("handleSelectionChange", val);
}

function regexTypeChange(item, val) {
  const t = regexTypeList.value.find(t => t.regexType === val);
  item.regexText = t.regexText;
  item.errorMsg = t.errorMsg;
}

async function onSearch() {
  loading.value = true;
  let { data } = await getList({
    sqlTag: form.sqlTag,
    dataSourceName: form.dataSourceName,
    pageSize: pageSize.value,
    pageNum: pageNum.value
  });
  dataList.value = data?.list;
  totalPage.value = data?.total;
  setTimeout(() => {
    loading.value = false;
  }, 500);
}

const resetForm = (formEl: FormInstance | undefined) => {
  pageNum.value = 1;
  pageSize.value = 10;
  if (!formEl) return;
  formEl.resetFields();
  onSearch();
};

function handleAdd() {
  editFormRef.value?.resetFields();
  editId.value = null;
  editShow.value = true;
  editForm.value.parameterValidationList = [];
}

function addParamHandle() {
  editForm.value.parameterValidationList.push({
    paramName: "",
    regexType: "",
    regexText: "",
    errorMsg: ""
  });
}

function deleteParamHandle(param) {
  editForm.value.parameterValidationList.splice(
    editForm.value.parameterValidationList.findIndex(item => item === param),
    1
  );
}

onMounted(() => {
  onSearch();
  getAllList().then(res => {
    sourceList.value = res?.data || [];
  });
  getCommonValidatorAllList().then(res => {
    regexTypeList.value = res?.data || [];
  });
});
</script>

<template>
  <div class="main">
    <re-dialog
      v-model="editShow"
      :title="editId === null ? '动态SQL添加' : '动态SQL修改'"
    >
      <el-form
        :model="editForm"
        :label-width="100"
        ref="editFormRef"
        :rules="editRules"
        v-loading="editLoading"
      >
        <el-card
          shadow="never"
          style="margin-bottom: 18px"
          class="my-card request-body"
        >
          <template #header>
            <el-row type="flex" justify="space-between" align="middle">
              <span style="font-size: 16px">请求参数</span>
              <el-button :icon="Plus" type="primary" @click="addParamHandle" />
            </el-row>
          </template>

          <div
            class="empty text-center"
            v-if="
              editForm.parameterValidationList == null ||
              editForm.parameterValidationList.length === 0
            "
          >
            暂无
          </div>

          <el-form-item
            v-else
            v-for="(item, index) in editForm.parameterValidationList"
            :key="item"
            prop="parameterValidationList"
            label-width="0"
          >
            <el-row type="flex" style="width: 100%">
              <el-form-item
                :prop="`parameterValidationList[${index}].paramName`"
                :rules="[
                  {
                    required: true,
                    message: '参数名不能为空'
                  }
                ]"
                style="width: 120px"
              >
                <el-input
                  v-model="item.paramName"
                  clearable
                  placeholder="请输入参数名"
                />
              </el-form-item>
              <el-select
                v-model="item.regexType"
                placeholder="可选正则类型"
                style="width: 142px; margin-left: 12px"
                clearable
                @change="val => regexTypeChange(item, val)"
              >
                <el-option
                  :label="item.regexType"
                  :value="item.regexType"
                  v-for="item in regexTypeList"
                  :key="item"
                />
              </el-select>
              <el-form-item
                style="margin-left: 12px; width: 140px"
                :prop="`parameterValidationList[${index}].regexText`"
                :rules="[
                  {
                    required: true,
                    message: '正则文本不能为空'
                  }
                ]"
              >
                <el-input
                  v-model="item.regexText"
                  placeholder="请输入正则文本"
                  class="input-with-select"
                  :readonly="item.regexType !== ''"
                  clearable
                />
              </el-form-item>
              <el-form-item
                style="margin-left: 12px; flex: 1"
                :prop="`parameterValidationList[${index}].errorMsg`"
                :rules="[
                  {
                    required: true,
                    message: '错误信息不能为空'
                  }
                ]"
              >
                <el-input
                  v-model="item.errorMsg"
                  placeholder="请输入错误信息"
                  class="input-with-select"
                  :readonly="item.regexType !== ''"
                  clearable
                />
              </el-form-item>
              <el-button
                :icon="Delete"
                style="margin-left: 12px"
                @click="deleteParamHandle(item)"
              />
            </el-row>
          </el-form-item>
        </el-card>
        <el-card shadow="never" style="margin-bottom: 18px" class="my-card">
          <el-form-item label="sql标签：" prop="sqlTag">
            <el-input v-model="editForm.sqlTag" clearable />
          </el-form-item>
          <el-form-item label="结果key：" prop="sqlResultKey">
            <el-input v-model="editForm.sqlResultKey" clearable />
          </el-form-item>
          <el-form-item label="sql内容：" prop="sqlContent">
            <el-input
              v-model="editForm.sqlContent"
              type="textarea"
              rows="5"
              clearable
            />
          </el-form-item>
          <el-form-item label="结果类型：" prop="sqlType">
            <el-select
              v-model="editForm.sqlType"
              placeholder="请选择结果类型"
              style="width: 100%"
              clearable
            >
              <el-option label="list" value="list" />
              <el-option label="page" value="page" />
              <el-option label="object" value="object" />
              <el-option label="update" value="update" />
            </el-select>
          </el-form-item>
          <el-form-item label="数据源名：" prop="dataSourceName">
            <el-select
              v-model="editForm.dataSourceName"
              clearable
              placeholder="请选择数据源名"
              style="width: 100%"
            >
              <el-option
                v-for="item in sourceList"
                :key="item.id"
                :label="item.dataSourceName"
                :value="item.dataSourceName"
              />
            </el-select>
          </el-form-item>
        </el-card>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" style="width: 100px" @click="onSubmit">{{
            editId === null ? "添加" : "修改"
          }}</el-button>
          <el-button @click="editShow = false" style="width: 100px"
            >取消</el-button
          >
        </span>
      </template>
    </re-dialog>
    <el-form
      ref="formRef"
      :inline="true"
      :model="form"
      class="bg-white pl-8 pt-4"
    >
      <el-form-item label="sql标签：" prop="sqlTag">
        <el-input
          v-model="form.sqlTag"
          placeholder="请输入sql标签"
          clearable
          class="form-item-input"
        />
      </el-form-item>
      <el-form-item label="数据源名：" prop="dataSourceName">
        <el-select
          v-model="form.dataSourceName"
          clearable
          placeholder="请选择数据源名"
        >
          <el-option
            v-for="item in sourceList"
            :key="item.id"
            :label="item.dataSourceName"
            :value="`${item.id}`"
          />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button
          type="primary"
          :icon="useRenderIcon('search')"
          :loading="loading"
          @click="onSearch"
        >
          搜索
        </el-button>
        <el-button :icon="useRenderIcon('refresh')" @click="resetForm(formRef)">
          重置
        </el-button>
      </el-form-item>
    </el-form>

    <EpTableProBar
      title="动态SQL列表"
      :loading="loading"
      :dataList="dataList"
      @refresh="onSearch"
    >
      <template #buttons>
        <el-button
          type="primary"
          :icon="useRenderIcon('add')"
          @click="handleAdd"
        >
          添加
        </el-button>
      </template>
      <template v-slot="{ size }">
        <el-table
          border
          table-layout="auto"
          :size="size"
          :data="dataList"
          :header-cell-style="{ background: '#fafafa', color: '#606266' }"
          @selection-change="handleSelectionChange"
        >
          <el-table-column
            label="sql标签"
            align="center"
            prop="sqlTag"
            width="120"
            fixed="left"
          >
            <template #default="scope">
              <ReTextHighlight
                :content="scope.row.sqlTag"
                :searchText="form.sqlTag"
              />
            </template>
          </el-table-column>
          <el-table-column
            label="结果key"
            align="center"
            prop="sqlResultKey"
            width="100"
          />
          <el-table-column
            label="sql内容"
            align="center"
            prop="sqlContent"
            min-width="200"
          />
          <el-table-column
            label="结果类型"
            align="center"
            prop="sqlType"
            width="100"
          />
          <el-table-column
            label="数据源名"
            align="center"
            prop="dataSourceName"
            width="100"
          />
          <el-table-column
            label="更新时间"
            align="center"
            width="180"
            prop="updateTime"
            :formatter="
              ({ updateTime }) => {
                return dayjs(updateTime).format('YYYY-MM-DD HH:mm:ss');
              }
            "
          />
          <el-table-column
            fixed="right"
            label="操作"
            width="150"
            align="center"
          >
            <template #default="scope">
              <el-button
                class="reset-margin"
                type="text"
                :size="size"
                @click="handleUpdate(scope.row)"
                :icon="useRenderIcon('edits')"
              >
                修改
              </el-button>
              <el-popconfirm
                title="是否确认删除?"
                @confirm="handleDelete(scope.row)"
              >
                <template #reference>
                  <el-button
                    class="reset-margin"
                    type="text"
                    :size="size"
                    :icon="useRenderIcon('delete')"
                  >
                    删除
                  </el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
          class="flex justify-end mt-4"
          :small="size === 'small'"
          v-model:page-size="pageSize"
          :page-sizes="[10, 20, 30, 50]"
          :background="true"
          layout="total, sizes, prev, pager, next, jumper"
          :total="totalPage"
          :current-page="pageNum"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </template>
    </EpTableProBar>
  </div>
</template>

<style scoped lang="scss">
@import "../system.scss";

.request-body {
  :deep(.el-card__header) {
    padding: 10px 12px;
  }

  :deep(.el-input-group__append),
  :deep(.el-input-group__prepend) {
    background-color: var(--el-input-bg-color, var(--el-fill-color-blank));
  }

  :deep(.el-form-item__label) {
    display: flex;
    width: 160px !important;
  }
}
</style>
